﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Net;
using System.IO;
using System.Xml;
namespace GoearAPI
{
    public class GoearAPI
    {
        public const String ERR_NO_XML = "ERR_NO_XML";
        public const String ERR_WRONG_URL = "ERR_WRONG_URL";
        public const String ERR_EMPTY_LINE = "ERR_EMPTY_LINE";

        private String regexSongId,regexSongIdOld, regexUrlPattern, regexUrlPatternOld;
        private String trackerUrl = "";

        private String outputDir = "";
        public String OutputDir {
            get { return outputDir; }
            set { outputDir = value; }
        }

        private WebClient webHandler;
        
        /// <summary>
        /// Class constructor. Initializes the requires vars for the rest of the process
        /// </summary>
        public GoearAPI() {
            this.trackerUrl = "http://www.goear.com/tracker758.php?f=";
            this.outputDir = "C:\\";
            this.regexUrlPattern = "^http://www.goear.com/listen/([a-zA-Z0-9]|\\-)+/\\S+$";
            this.regexUrlPatternOld = "^http://www.goear.com/listen.php\\?v=([a-zA-Z0-9]|\\-)+$";
            this.regexSongId = "\\b/listen/([A-Za-z0-9]|\\-)+/\\b";
            this.regexSongIdOld = "\\bv=([a-zA-Z0-9]|\\-|\\_)+\\b";

            this.webHandler = new WebClient();
        }

        /// <summary>
        /// Main public method of the class.
        /// </summary>
        /// <param name="file_url">A String with song URL e.g. "http://www.goear.com/listen/eac617a/title-artist"</param>
        /// <returns>A String The real URL of the mp3 file to download</returns>
        public List<String> getFile(String file_url) {
            List<String> returnVar = new List<String>();
            String songId = "";
            //if not empty
            if (file_url.Trim().Length == 0)
            {
                returnVar.Add(ERR_EMPTY_LINE);
                return returnVar;
            }
            //if file_url matches the modern url pattern used by goear
            if ((Regex.IsMatch(file_url, this.regexUrlPattern) && Regex.IsMatch(file_url, this.regexSongId)) )
            {
                //we extract the string between "listen/" and the last slash "/"
                String resultString = Regex.Match(file_url, this.regexSongId).Value;
                String[] splitArray = Regex.Split(resultString, "/");
                songId = splitArray[2];
            }
            //if file_url matches the old pattern used by goear
            else if (Regex.IsMatch(file_url, this.regexUrlPatternOld) && Regex.IsMatch(file_url, this.regexSongIdOld))
            {
                //we extract the string at the end of the url, starting after the "v="
                String resultString = Regex.Match(file_url, this.regexSongIdOld).Value;
                resultString = resultString.Remove(0, 2);
                songId = resultString;
            }
            else {
                //if none of the above, return an error
                returnVar.Add(ERR_WRONG_URL);
                return returnVar;
            }
                
            //now, we call the "tracker" URL with the song_id extracted above.
            //this will return an XML string which we may parse.
            //<songs><song path="x" value="y"></song></songs>
            //We must get the X and Y values and return them in an array 
            //where a[0] is the path and a[1] is the title
             try {
                byte[] downloadedData = this.webHandler.DownloadData(this.trackerUrl.ToString() + songId);
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(Encoding.UTF8.GetString(downloadedData));
                XmlNodeList songs = doc.GetElementsByTagName("song");
                XmlNode song = songs.Item(0);
                String songPath = song.Attributes["path"].Value;
                String songName = song.Attributes["title"].Value;
                returnVar.Add(songPath);
                returnVar.Add(songName); 
            } catch (Exception) {
                //if something happens or nothing is found, return an error
                returnVar.Clear();
                returnVar.Add(ERR_NO_XML);
            }
            return returnVar;
        }
    
        /// <summary>
        /// Sets the webHandler object to use a Proxy with the arguments as credentials
        /// </summary>
        /// <param name="proxyType">HTTP / Socks4 / Socks5</param>
        /// <param name="hostName">Hostname</param>
        /// <param name="port">Port</param>
        /// <param name="userName">Username</param>
        /// <param name="password">Password</param>
        /// <returns>Boolean result of the operation</returns>
        public Boolean useProxy(String proxyType, String hostName,Int32 port, String userName, String password) {
            Boolean retVal = true;
            try
            {
                WebProxy wp = new WebProxy(hostName + ":" + port.ToString());
                wp.Credentials = new NetworkCredential(userName, password);
                this.webHandler.Proxy = wp;
                retVal = true;
            }
            catch {
                retVal = false;
            }
            return retVal;
        }

        /// <summary>
        /// Sets the webHandler object to use no Proxy
        /// </summary>
        /// <returns>Boolean result of the operation</returns>
        public Boolean dontUseProxy() {
            Boolean retVal = true;
            try
            {
                this.webHandler.Proxy = null;
                retVal = true;
            }
            catch
            {
                retVal = false;
            }
            return retVal;

        }
    }
}
